using Gtk;
using GLib;
using SerialPort;

namespace Magicom {

    public abstract class BaseWindow : Gtk.ApplicationWindow, SerialPortObserver
    {
        protected BaseController controller;
        
        public BaseWindow(Gtk.Application application)
        {
            GLib.Object (application: application);
            
            controller = new Controller(this);
            
            init();
        }
        
        protected abstract void port_init();
        
        public virtual void init()
        {
            port_init();
        }
        
        public virtual void data_report(uint8[] data, int size)
        {
            //default data report
            GLib.stdout.write(data[0 : size - 1]);
        }
    }

    [GtkTemplate(ui = "/org/gtk/magicom/window.ui")]
    public class Window : BaseWindow
    {        
        [GtkChild]
        Gtk.ComboBox combobox_port;
        
        [GtkChild]
		Gtk.TextView textview_output;
		
        [GtkChild]
        Gtk.TextBuffer textbuffer_output;
        
        [GtkChild]
		Gtk.CheckButton checkbutton_newline;
		
		[GtkChild]
		Gtk.Button button_send;

		[GtkChild]
		Gtk.Entry entry_send;
        
        public Window (Gtk.Application application)
        {
            base(application);
        }
        
        protected override void port_init()
        {
            Gtk.TreeIter iter;
            Gtk.ListStore model;
            
            var ports = controller.port_enum();
            
            model = combobox_port.get_model() as Gtk.ListStore;

            foreach(string port in ports)
            {
                model.append(out iter);
            
                model.set(iter, 0, port);
            }
            
            if(ports.length > 0)
            {
                combobox_port.set_active(0);
            }
        }
        
        public override void data_report(uint8[] data, int size)
        {
            Gtk.TextIter iter;
            
			textbuffer_output.get_end_iter(out iter);
			
	        textbuffer_output.insert(ref iter, (string)data, size);	
        }
        
        [GtkCallback]
        public void on_combobox_port_change(Gtk.ComboBox combobox)
        {
            GLib.Value @value;
            Gtk.TreeIter iter;
            Gtk.ListStore model;
            
            combobox.get_active_iter(out iter);
            
            model = combobox.get_model() as Gtk.ListStore;
            
            model.get_value(iter, 0, out @value);
            
            controller.port_change((string)@value);
        }

        [GtkCallback]
		public void on_textview_output_size_allocate(Gtk.Allocation allocation)
		{
		    Gtk.TextIter iter;
			
			textbuffer_output.get_end_iter(out iter);
			
			textview_output.scroll_to_iter(iter, 0, false, 0, 0);
		}
		
		[GtkCallback]
		public void on_button_clear_clicked(Gtk.Button button)
		{	
			textbuffer_output.set_text("");
		}
		
		[GtkCallback]
        public void on_button_switch_clicked(Gtk.Button button)
        {   
            switch(button.get_label())
            {
                case "Open":
                    if(true == controller.port_open())
                    {
                        button_send.sensitive = true;
                        button.label = "Close";
                    }
                    break;
                    
                case "Close":
                    controller.port_close();
                    button_send.sensitive = false;
                    button.label = "Open";
                    break;
            }
        }

		[GtkCallback]
		public void on_button_send_clicked()
		{
			controller.port_send(entry_send.get_text(), checkbutton_newline.get_active());
		}
    }
}
